home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / curses / v_doscur.c < prev    next >
Text File  |  1994-05-07  |  12KB  |  489 lines

  1. /*
  2.  *  Module    v_doscur        MSDOS-specific video routines
  3.  *  Author    larry gensch, ESQ
  4.  *
  5.  *  Copyright (c) 1987, 1988, 1989
  6.  *    by Larry Gensch  /  104 Lowell Road  /  Salem, NH  03079
  7.  *
  8.  *  This code may be included in any work, public or private, with the
  9.  *  exception of creating a commercial curses-compatible subroutine
  10.  *  library.  (In other words, use the code all you want, but please don't
  11.  *  rip off the author by reselling this code as your own).
  12.  *
  13.  *  If you make modifications to this code (specifically, enhancements that
  14.  *  are compatible with System V.x curses), please send them to larry gensch at
  15.  *  the address above to be considered for inclusion in subsequent releases.
  16.  *  Any machine specific implementation modules (similar to v_doscur.c) for
  17.  *  other machines are welcomed.
  18.  *
  19.  *  v_doscur.c is a machine-specific driver for curses that writes directly to
  20.  *  the memory mapped video display.  Currently, there is NO support for color
  21.  *  or routines using PADS (windows larger than the physical terminal screen).
  22.  *  To port curses to a new machine, this is the module that will have to be
  23.  *  reimplemented.
  24.  *  
  25.  */
  26.  
  27. #include "curses.h"
  28.  
  29. #include <ctype.h>
  30. #include <stdarg.h>
  31. #include <stdlib.h>
  32.  
  33. /*
  34.  * EXPORT is used to show entry points into this module.  Simply grep
  35.  * using the pattern '^EXPORT' to list them out.
  36.  */
  37.  
  38. #ifndef EXPORT
  39. #define EXPORT
  40. #endif
  41.  
  42. static unsigned    GetDS    (void);
  43. static void    Doinit        (int *lines, int *cols);
  44. static void    Mapscreen    (WINDOW *win);
  45. static void    Dispscreen    (void);
  46. static void    Setcursor    (int line, int col);
  47. static void    Dosrestore    (void);
  48. static bool    Kbhit        (void);
  49. static int    Getkey        (bool raw);
  50.  
  51. /*
  52.  * ms_init() - Perform any necessary initializations of the terminal or to
  53.  * the implementation module.  The LINES and COLS variables should be set
  54.  * as well.
  55.  */
  56.  
  57. EXPORT bool    ms_init        (void)
  58. {
  59.     Doinit(&LINES, &COLS);
  60.  
  61.     return TRUE;
  62. }
  63.  
  64. /*
  65.  * ms_refresh() - Refresh a WINDOW image onto our internal representation
  66.  * of our screen.  outflag specifies whether or not the actual display
  67.  * should be updated.  Returns ERR if an error occurred.
  68.  *
  69.  * Note:  If win is NULL, just update the display.
  70.  */
  71.  
  72. EXPORT int    ms_refresh    (WINDOW *win, bool outflag)
  73. {
  74.     static int    Lastcol = 0;    /* Save latest cursor position.  No provision here for */
  75.     static int    Lastrow = 0;    /*   invisible cursor. */
  76.  
  77.     if (win)
  78.         Mapscreen(win);
  79.  
  80.     if (win) {
  81.         if (! win->_leave) {
  82.             Lastrow = _CURS_CURSOR_SCREEN_ROW(win);
  83.             Lastcol = _CURS_CURSOR_SCREEN_COL(win);
  84.         }
  85.     }
  86.  
  87.     if (outflag) {
  88.         Dispscreen();
  89.         Setcursor(Lastrow, Lastcol);
  90.     }
  91.  
  92.     return OK;
  93. }
  94.  
  95. /*
  96.  * ms_end() - Restore the display so that a non-curses application can use
  97.  * it.  (Restore terminal modes, move cursor to lower left corner, etc.)
  98.  */
  99.  
  100. EXPORT bool    ms_end        (void)
  101. {
  102.     Setcursor(LINES - 1, 0);
  103.     return OK;
  104. }
  105.  
  106. /*
  107.  * ms_restore_scrn() - Allows user to repaint screen as it was before curses initialization.
  108.  */
  109.  
  110. EXPORT void ms_restore_scrn    (void)
  111. {
  112.     Dosrestore();
  113. }
  114.  
  115. /*
  116.  * ms_beep() - Sound the workstation alarm.  If flag is TRUE, then the
  117.  * workstation should be flashed, instead, if possible.
  118.  */
  119.  
  120. EXPORT void    ms_beep        (int flag)
  121. {
  122.     fputc('\a', stderr);
  123. }
  124.  
  125. /*
  126.  * ms_kbinp() - Get input from keyboard.
  127.  */
  128.  
  129. EXPORT int    ms_kbinp    (WINDOW *win, bool raw, bool cbreak)
  130. {
  131.     if (win->_nodelay) {
  132.         if (! Kbhit())
  133.             return ERR;
  134.     }
  135.  
  136.     Setcursor(_CURS_CURSOR_SCREEN_ROW(win),
  137.                                 _CURS_CURSOR_SCREEN_COL(win));
  138.     return Getkey(raw);
  139. }
  140.  
  141. /*
  142.  * ms_flushinp() - Throw away pending keyboard input.
  143.  */
  144.  
  145. EXPORT void ms_flushinp    (void)
  146. {
  147.     while (Kbhit()) getch();
  148. }
  149.  
  150.  
  151. /*
  152.  * Alternate Character Set table:
  153.  *
  154.  * Line drawing characters are named as follows:
  155.  *
  156.  *        t
  157.  *
  158.  *        |
  159.  *    l     --+--    r
  160.  *        |
  161.  *
  162.  *        b
  163.  *
  164.  * ACS_trbl (t=top, r=right, b=bottom, l=left)
  165.  *
  166.  * Valid values for each placeholder:
  167.  *
  168.  * B (blank)    S (single)    D (double)    T (thick)
  169.  *
  170.  * Curses (currently) only supports B and S.
  171.  */
  172.  
  173. EXPORT chtype    acs_map[256] = {
  174.     0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   ,
  175.     0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   ,
  176.     0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   ,
  177.     0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   ,
  178.     0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   ,
  179.     0x0   , 0x0   , 0x0   , 0x801a, 0x801b, 0x8018, 0x8019, 0x0   ,
  180.     0x805b, 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   ,
  181.     0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   ,
  182.     0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   ,
  183.     0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   ,
  184.     0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   ,
  185.     0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x0   ,
  186.     0x8004, 0x8030, 0x0   , 0x0   , 0x0   , 0x0   , 0x8078, 0x8071,
  187.     0x8032, 0x8068, 0x8059, 0x803f, 0x805a, 0x8040, 0x8045, 0x805f,
  188.     0x0   , 0x8044, 0x0   , 0x802d, 0x8043, 0x8034, 0x8041, 0x8042,
  189.     0x8033, 0x0   , 0x0   , 0x0   , 0x0   , 0x0   , 0x8007, 0x0   ,
  190. };
  191.  
  192. /* -------------------------------------------- */
  193. /*        Private routines and variables        */
  194. /* -------------------------------------------- */
  195.  
  196. static const unsigned    Monobase = 0xB000;    
  197. static const unsigned    Colrbase = 0xB800;
  198.  
  199. #if defined (__WATCOMC__) && defined (__386__)
  200. #    define INT86_FN int386
  201. #else
  202. #    define INT86_FN int86
  203. #endif
  204.  
  205. typedef struct CHAR {
  206.     char    ch;
  207.     char    at;
  208. } CHAR;
  209.  
  210. static CHAR    *Screen;        /* PC Screen image        */
  211. static void        *Oldscreen = NULL;    /* Saved screen image */
  212. static unsigned Screenbase = 0;        /* Segment for OUR machine    */
  213.  
  214. #define VIDEO_INT    0x10        /* Video interrupt        */
  215.  
  216. #define CUR_SIZE    0x1        /* Set cursor size        */
  217. #define SET_POSN    0x2        /* Modify cursor posn        */
  218. #define GET_POSN    0x3        /* Read current cursor posn    */
  219. #define WRITE        0x9        /* Write character        */
  220. #define WRITE_TTY    0xe        /* Write char & move cursor    */
  221. #define GET_VMODE    0xf        /* Get video mode & disp pg    */
  222.  
  223. #undef getch            /* Defn in conio.h        */
  224.  
  225. #include <dos.h>
  226. #include <string.h>
  227. #include <conio.h>
  228.  
  229. static union REGS    Regs;            /* Used to talk to DOS    */
  230. static int        Xmax = 0;        /* Number of columns    */
  231. static int        Ymax = 0;        /* Number of rows    */
  232.  
  233. #define ATTR_NORM       0x07    /* Normal attr        *lg*    */
  234. #define ATTR_SOUT       0x70    /* Standout attr    *lg*    */
  235. #define ATTR_UOUT       0x01    /* Underline attr    *lg*    */
  236. #define    ATTR_BOUT    0x80    /* Blinking attr    *lg*    */
  237. #define    ATTR_BOLD    0x08    /* Bold attr        *lg*    */
  238.  
  239. #define SCAN_BACKSPACE    '\b'        /* Backspace key    */
  240. #define    SCAN_EXIT    0x001B        /* Exit key (ESC)    */
  241. #define    SCAN_CBACKSPACE    0x007F        /* Ctrl + Backspace    */
  242. #define    SCAN_BTAB    0x010F        /* Shift + Tab key    */
  243. #define    SCAN_F1        0x013B        /* Function key 1    */
  244. #define SCAN_HOME    0x0147        /* Home key        */
  245. #define    SCAN_UP        0x0148        /* Up arrow        */
  246. #define    SCAN_PPAGE    0x0149        /* PgUp key        */
  247. #define    SCAN_LEFT    0x014B        /* Left arrow        */
  248. #define SCAN_RIGHT    0x014D        /* Right arrow        */
  249. #define    SCAN_END    0x014F        /* End key        */
  250. #define SCAN_DOWN    0x0150        /* Down arrow        */
  251. #define    SCAN_NPAGE    0x0151        /* PgDn key        */
  252. #define    SCAN_IC        0x0152        /* Ins key        */
  253. #define    SCAN_DC        0x0153        /* Del key        */
  254. #define    SCAN_SF1    0x0154        /* Shift + F Key 1    */
  255. #define    SCAN_CF1    0x015E        /* Ctrl + F Key 1    */
  256. #define    SCAN_AF1    0x0168        /* Alt + F Key 1    */
  257. #define    SCAN_SLEFT    0x0173        /* Ctrl + Left arrow    */
  258. #define    SCAN_SRIGHT    0x0174        /* Ctrl + Right arrow    */
  259. #define SCAN_SEND    0x0175        /* Ctrl + End key    */
  260. #define    SCAN_CNPAGE    0x0176        /* Ctrl + PgDn        */
  261. #define    SCAN_SHOME    0x0177        /* Ctrl + Home key    */
  262. #define SCAN_CPPAGE    0x0184        /* Ctrl + PgUp        */
  263.  
  264. /*
  265.  * GetDS() - Return the data segment as an unsigned value.
  266.  */
  267.  
  268. static unsigned    GetDS        (void)
  269. {
  270.     struct SREGS seg;
  271.  
  272.     segread(&seg);
  273.  
  274.     return seg.ds;
  275. }
  276.  
  277. /*
  278.  * Doinit() - Perform our initializations, and set lines and columns.
  279.  */
  280.  
  281. static void    Doinit        (int *lines, int *cols)
  282. {
  283.     register    int i;
  284.     CHAR    *ptr;
  285.     char *src_ptr;
  286.  
  287.     Regs.h.ah = GET_VMODE;
  288.  
  289.     INT86_FN( VIDEO_INT, &Regs, &Regs );
  290.  
  291.     *cols  = Xmax = Regs.h.ah;
  292.     *lines = Ymax = 25;
  293.  
  294.     if (Screen == NULL)
  295.         Screen = (CHAR *)malloc(Xmax * Ymax * sizeof(CHAR));
  296.  
  297.     if (Screen == NULL) {
  298.         fputs("v_doscur: memory allocation failure.\n", stderr);
  299.         exit(1);
  300.     }
  301.     
  302.     for (ptr = Screen, i = *lines * *cols; i >= 0; i--, ptr++) {
  303.         ptr->ch = ' ';
  304.         ptr->at = ATTR_NORM;
  305.     }
  306.  
  307.     if (Regs.h.al == 7)
  308.         Screenbase = Monobase;
  309.     else
  310.         Screenbase = Colrbase;
  311.  
  312.     if (Oldscreen == NULL)
  313.         Oldscreen = malloc(Xmax * Ymax * 2);
  314.  
  315.     if (Oldscreen == NULL) {
  316.         fputs("v_doscur: memory allocation failure.\n", stderr);
  317.         exit(1);
  318.     }
  319.  
  320. #if defined (__WATCOMC__) && defined (__386__)
  321.     src_ptr = (Screenbase << 4);
  322.     memcpy(Oldscreen, src_ptr, Xmax * Ymax * 2);
  323. #else
  324.     movedata(Screenbase, 0, GetDS(), (unsigned) Oldscreen, Xmax * Ymax * 2);
  325. #endif
  326. }
  327.  
  328. /*
  329.  * Mapscreen() - Copy the screen image given to us by CURSES into our
  330.  * internal display representation.
  331.  */
  332.  
  333. static void    Mapscreen    (WINDOW *win)
  334. {
  335.     int        maxx, maxy, i_rw, i;
  336.     chtype    *src_ptr, attr;
  337.     CHAR    *sptr, *dst_ptr;
  338.  
  339.     if (win->_begy < Ymax && win->_begx < Xmax)
  340.     {
  341.         dst_ptr = Screen + (win->_begy * Xmax) + win->_begx;
  342.         if (win->_flags & _ISPAD)
  343.         {
  344.             maxx = win->_pmap_maxx - win->_pmap_orgx;                /* For pads, get # rows and columns to display. */
  345.             maxy = win->_pmap_maxy - win->_pmap_orgy;
  346.             src_ptr = win->_y +                                        /* Point to 1st displayed character in pad. */
  347.                             ((win->_pmap_orgy * win->_xdim) +
  348.                             win->_pmap_orgx);
  349.         }
  350.         else
  351.         {
  352.             maxx = win->_maxx;
  353.             maxy = win->_maxy;
  354.             src_ptr = win->_y;
  355.         }
  356.  
  357.         maxy = MIN(maxy, Ymax - win->_begy);
  358.         maxx = MIN(maxx, Xmax - win->_begx);
  359.  
  360.         for (i_rw = 0; i_rw < maxy; i_rw++,                            /* Copy text from window to screen image. */
  361.                             dst_ptr += Xmax, src_ptr += win->_xdim)
  362.         {
  363.             for (i = 0; i < maxx; i++)
  364.             {
  365.                 sptr = dst_ptr + i;
  366.                 attr = *(src_ptr + i) & A_ATTRIBUTES;
  367.  
  368.                 sptr->ch = *(src_ptr + i) & A_CHARTEXT;
  369.  
  370.                 if (attr & A_ALTCHARSET)
  371.                     sptr->ch |= 0x80;
  372.  
  373.                 sptr->at = ATTR_NORM;
  374.  
  375.                 if (attr & A_STANDOUT)
  376.                     sptr->at = ATTR_SOUT;
  377.                 if (attr & A_REVERSE)
  378.                     sptr->at = ATTR_SOUT;
  379.                 if (attr & A_UNDERLINE)
  380.                     sptr->at = ATTR_UOUT;
  381.                 if (attr & A_BOLD)
  382.                     sptr->at |= ATTR_BOLD;
  383.                 if (attr & A_BLINK)
  384.                     sptr->at |= ATTR_BOUT;
  385.             }
  386.         }
  387.     }
  388. }
  389.  
  390. /*
  391.  * Dispscreen() - Make the physical screen look like our internal screen.
  392.  */
  393.  
  394. static void    Dispscreen    (void)
  395. {
  396. #if defined (__WATCOMC__) && defined (__386__)
  397.     char *src_ptr = (Screenbase << 4);
  398.     memcpy(src_ptr, Screen, Xmax * Ymax * 2);
  399. #else
  400.     movedata(GetDS(), (unsigned) Screen, Screenbase, 0, Xmax * Ymax * 2);
  401. #endif
  402. }
  403.  
  404. /*
  405.  * Setcursor() - Set the cursor to the specified location.
  406.  */
  407.  
  408. static void    Setcursor    (int line, int col)
  409. {
  410.     Regs.h.ah = GET_VMODE;
  411.     INT86_FN( VIDEO_INT, &Regs, &Regs );
  412.  
  413.     Regs.h.dh = MIN(line, Ymax - 1);
  414.     Regs.h.dl = MIN(col, Xmax - 1);
  415.     Regs.h.ah = SET_POSN;
  416.     INT86_FN(VIDEO_INT, &Regs, &Regs);
  417. }
  418.  
  419. /*
  420.  * Dosrestore() - Restore the screen to what it was before we started()'d
  421.  */
  422.  
  423. static void    Dosrestore    (void)
  424. {
  425.     if (Oldscreen != NULL)
  426.     {
  427. #if defined (__WATCOMC__) && defined (__386__)
  428.         char *scr_ptr = (Screenbase << 4);
  429.         memcpy(scr_ptr, Oldscreen, Xmax * Ymax * 2);
  430. #else
  431.         movedata(GetDS(), (unsigned) Oldscreen, Screenbase, 0, Xmax * Ymax * 2);
  432. #endif
  433.     }
  434. }
  435.  
  436. /*
  437.  * Kbhit() - Returns TRUE if a character in the k/b buffer, else FALSE.
  438.  */
  439.  
  440. static bool    Kbhit        (void)
  441. {
  442.     return kbhit();
  443. }
  444.  
  445. static int    Getkey        (bool raw)
  446. {
  447.     int        c;
  448.  
  449.     if (raw)
  450.         return getch();
  451.  
  452.     c = getch();
  453.     if (c == 0)
  454.         c = getch() | 0x100;
  455.  
  456.     if (c >= SCAN_F1 && c <= SCAN_F1+9)
  457.         return KEY_F(c-SCAN_F1+1);
  458.     if (c >= SCAN_SF1 && c <= SCAN_SF1+9)
  459.         return KEY_F(c-SCAN_SF1+11);
  460.     if (c >= SCAN_CF1 && c <= SCAN_CF1+9)
  461.         return KEY_F(c-SCAN_CF1+21);
  462.     if (c >= SCAN_AF1 && c <= SCAN_AF1+9)
  463.         return KEY_F(c-SCAN_AF1+31);
  464.  
  465.     switch (c) {
  466.         case SCAN_DOWN:        return KEY_DOWN;
  467.         case SCAN_UP:        return KEY_UP;
  468.         case SCAN_LEFT:        return KEY_LEFT;
  469.         case SCAN_RIGHT:    return KEY_RIGHT;
  470.         case SCAN_HOME:        return KEY_HOME;
  471.         case SCAN_BACKSPACE:    return KEY_BACKSPACE;
  472.         case SCAN_DC:        return KEY_DC;
  473.         case SCAN_IC:        return KEY_IC;
  474.         case SCAN_NPAGE:    return KEY_NPAGE;
  475.         case SCAN_PPAGE:    return KEY_PPAGE;
  476.         case SCAN_CNPAGE:    return KEY_SF;
  477.         case SCAN_CPPAGE:    return KEY_SR;
  478.         case SCAN_BTAB:        return KEY_BTAB;
  479.         case SCAN_END:        return KEY_END;
  480.         case SCAN_EXIT:        return KEY_EXIT;
  481.         case SCAN_SEND:        return KEY_SEND;
  482.         case SCAN_SHOME:    return KEY_SHOME;
  483.         case SCAN_SLEFT:    return KEY_SLEFT;
  484.         case SCAN_SRIGHT:    return KEY_SRIGHT;
  485.         default:
  486.             return c & 0xff;
  487.     }
  488. }
  489.